#include "data.hpp"
#include "httplib.h"

namespace aod
{
#define WWWROOT "./www"
#define VIDEO_ROOT "/video/"
#define IMAGE_ROOT "/image/"
    TableVideo *tb_video = nullptr;

    class Server
    {
    private:
        int _port;            // 服务器的 监听端口
        httplib::Server _srv; // 用于搭建http服务器
    private:
        // 对应的业务处理接口
        static void Insert(const httplib::Request &req, httplib::Response &rsp)
        {
            if (req.has_file("name") == false ||
                req.has_file("info") == false ||
                req.has_file("video") == false ||
                req.has_file("image") == false)
            {
                rsp.status == 400;
                rsp.body = R"({"result":false, "reason":"上传数据信息错误"})";
                rsp.set_header("Content-Type", "application/json");
                return;
            }
            httplib::MultipartFormData name = req.get_file_value("name");
            httplib::MultipartFormData info = req.get_file_value("info");
            httplib::MultipartFormData video = req.get_file_value("video");
            httplib::MultipartFormData image = req.get_file_value("image");

            std::string video_name = name.content;
            std::string video_info = info.content;
            std::string wwwroot = WWWROOT;
            std::string video_path = wwwroot + VIDEO_ROOT + video_name + video.filename;
            std::string image_path = wwwroot + IMAGE_ROOT + video_name + image.filename;

            if (FileUtil(video_path).SetContent(video.content) == false)
            {
                rsp.status = 500;
                rsp.body = R"({"result":false, "reason":"视频存储错误"})";
                rsp.set_header("Content-Type", "application/json");
                return;
            }
            if (FileUtil(image_path).SetContent(image.content) == false)
            {
                rsp.status = 500;
                rsp.body = R"({"result":false, "reason":"文件存储错误"})";
                rsp.set_header("Content-Type", "application/json");
                return;
            }
            Json::Value video_json;
            video_json["name"] = video_name;
            video_json["info"] = video_info;
            video_json["video"] = VIDEO_ROOT + video_name + video.filename;
            video_json["image"] = IMAGE_ROOT + video_name + image.filename;
            if (tb_video->Insert(video_json) == false)
            {
                rsp.status = 500;
                rsp.body = R"({"result":false, "reason":"数据库新增失败"})";
                rsp.set_header("Content-Type", "application/json");
                return;
            }
            return;
        }
        static void Update(const httplib::Request &req, httplib::Response &rsp)
        {
            int video_id = std::stoi(req.matches[1]);

            Json::Value video;
            if (JsonUtil::UnSerialize(req.body, &video) == false)
            {
                rsp.status = 400;
                rsp.body = R"({"result":false, "reason":"新的视频信息解析失败"})";
                rsp.set_header("Content-Type", "application/json");
                return;
            }
            if (tb_video->Update(video_id, video) == false)
            {
                rsp.status = 500;
                rsp.body = R"({"result":false, "reason":"修改数据库失败"})";
                rsp.set_header("Content-Type", "application/json");
                return;
            }
            return;
        }

        static void Delete(const httplib::Request &req, httplib::Response &rsp)
        {
            int video_id = std::stoi(req.matches[1]);

            Json::Value video;
            if (tb_video->SelectOne(video_id, &video) == false)
            {
                rsp.status = 500;
                rsp.body = R"({"result":false, "reason":"不存在视频"})";
                rsp.set_header("Content-Type", "application/json");
                return;
            }
            std::string wwwroot = WWWROOT;
            std::string video_path = wwwroot + video["video"].asString();
            std::string image_path = wwwroot + video["image"].asString();
            remove(video_path.c_str());
            remove(image_path.c_str());

            if (tb_video->Delete(video_id) == false)
            {
                rsp.status = 500;
                rsp.body = R"({"result":false, "reason":"删除失败"})";
                rsp.set_header("Content-Type", "application/json");
                return;
            }
            return;
        }
        static void SelectOne(const httplib::Request &req, httplib::Response &rsp)
        {
            int video_id = std::stoi(req.matches[1]);

            Json::Value video;
            if (tb_video->SelectOne(video_id, &video) == false)
            {
                rsp.status = 500;
                rsp.body = R"({"result":false, "reason":"查询一个失败"})";
                rsp.set_header("Content-Type", "application/json");
                return;
            }
            JsonUtil::Serialize(video, &rsp.body);
            rsp.set_header("Content-Type", "application/json");
            return;
        }
        static void SelectAll(const httplib::Request &req, httplib::Response &rsp)
        {
            bool select_flag = true;
            std::string search_key;
            if (req.has_param("search") == true)
            {
                select_flag = false;
                search_key = req.get_param_value("search");
            }
            Json::Value video;
            if (select_flag == true)
            {
                if (tb_video->SelectAll(&video) == false)
                {
                    rsp.status = 500;
                    rsp.body = R"({"result":false, "reason":"查询所有失败"})";
                    rsp.set_header("Content-Type", "application/json");
                    return;
                }
            }
            else
            {
                if (tb_video->SelectLike(search_key, &video) == false)
                {
                    rsp.status = 500;
                    rsp.body = R"({"result":false, "reason":"查询数据库匹配视频失败"})";
                    rsp.set_header("Content-Type", "application/json");
                    return;
                }
            }

            JsonUtil::Serialize(video, &rsp.body);
            rsp.set_header("Content-Type", "application/json");
            return;
        }

    public:
        Server(int port)
            : _port(port)
        {
        }
        bool RunModule() // 建立请求与处理函数的映射关系，设置静态资源根目录，启动服务器，
        {
            // 先进行初始化
            tb_video = new TableVideo();
            FileUtil(WWWROOT).CreateDirectory();

            std::string wwwroot = WWWROOT;

            std::string video_real_path = wwwroot + VIDEO_ROOT;
            FileUtil(video_real_path).CreateDirectory();

            std::string image_real_path = wwwroot + IMAGE_ROOT;
            FileUtil(image_real_path).CreateDirectory();
            // 搭建http服务器
            _srv.set_mount_point("/", WWWROOT);

            _srv.Post("/video", Insert);
            _srv.Delete("/video/(\\d+)", Delete);
            _srv.Put("/video/(\\d+)", Update);
            _srv.Get("/video/(\\d+)", SelectOne);
            _srv.Get("/video", SelectAll);
            // 启动
            _srv.listen("0.0.0.0", _port);
            return true;
        }
    };
} 
